package cn.heygod.graywhale.runtime.task.exe;

import cn.heygod.graywhale.runtime.context.Input;
import cn.heygod.graywhale.runtime.context.Output;
import cn.heygod.graywhale.runtime.exception.ServiceException;
import cn.heygod.graywhale.runtime.script.JavaScriptService;
import cn.heygod.graywhale.runtime.script.ScriptService;
import cn.heygod.graywhale.runtime.spring.SpringContextUtil;
import cn.hutool.core.util.ReflectUtil;

import java.util.HashMap;
import java.util.Map;

/**
 * @className: NodeExecutorFactory
 * @author: Simon
 * @description: TODO
 * @date: 2023/11/27 2:14
 * @version: 1.0
 */
public class NodeExecutorFactory {

    public static final String CLASS = "CLASS";
    public static final String SPRING = "SPRING";
    public static final String SCRIPT = "SCRIPT";

    private Map<String,NodeExecutor> executors = new HashMap<>();


    public static NodeExecutorFactory factory = null;

    public static NodeExecutorFactory me(){
        if(factory == null){
            factory = new NodeExecutorFactory();
            factory.executors.put(CLASS,new ClassNameNodeExecutor() );
            factory.executors.put(SPRING,new SpringBeanNodeExecutor() );
            factory.executors.put(SCRIPT,new JavascriptNodeExecutor() );
        }
        return factory;
    }

    public NodeExecutor executor(String type){
        return executors.get(type);
    }


    public static class ClassNameNodeExecutor implements NodeExecutor{

        @Override
        public Output run(String executorId, Input input) {
            Object obj = ReflectUtil.newInstance(executorId);
            if(obj instanceof TaskExecutable){
                return ((TaskExecutable)obj).run(input);
            }else {
                throw new ServiceException(executorId + " is not implements TaskExecutable");
            }
        }
    }

    public static class SpringBeanNodeExecutor implements NodeExecutor{

        @Override
        public Output run(String executorId, Input input) {
            TaskExecutable executable = SpringContextUtil.bean(executorId, TaskExecutable.class);
            return executable.run(input);
        }
    }

    public static class JavascriptNodeExecutor implements NodeExecutor{

        private ScriptService scriptService = null;

        @Override
        public Output run(String executorId, Input input) {
            if(scriptService==null){
                scriptService = SpringContextUtil.bean(ScriptService.class);
            }

            return scriptService.run(executorId, input);
        }
    }
}
